package com.hns.can.mainte.service;

import com.hns.can.mainte.entity.CommLogFileRcdEntity;
import com.hns.can.mainte.vo.LoadFileParamVo;
import com.hns.can.master.service.WebServiceBSService;
import com.hns.can.master.webservice.WebServiceClient;
import com.hns.frame.enumrate.MsgType;
import com.hns.frame.exception.BusinessException;
import com.hns.frame.service.CommonService;
import com.hns.tool.pub.JsonUtil;
import com.hns.tool.pub.PubUtil;
import com.hns.tool.pub.UFDateTime;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 文件下载管理Service
 *
 * @version Revision 2.0.0
 * @author:zhangzq
 * @email:
 */
@Service
public class LoadFileService extends CommonService {

    private static final Logger logger = LoggerFactory.getLogger(LoadFileService.class);

    @Autowired
    private LoadFileNService loadFileNService;
    @Autowired
    private WebServiceBSService webServiceBSService;

    // todo 获取设备上传的文件，记录文件上传下载日志

    /**
     * 获取设备上传的文件，记录文件上传下载日志
     *
     * @param conditionVo
     * @throws Exception
     */
    @Transactional
    public void saveLoadFile(LoadFileParamVo conditionVo) throws Exception {
        //查询时间段是否有未加载的时间区间
        HashMap<String, Object> timeBreakList = getTimeBreak(conditionVo);

        //如果有，发送相应的时间区间到设备,获取到返回的上传文件名
        ArrayList<String> files = new ArrayList<String>();
        if (PubUtil.isNotEmpty(timeBreakList)) {
            // 将时间区间转换成JSON发送到通讯服务端
            String json = JsonUtil.getJsonStringFromMap(timeBreakList);
            // 从通讯服务端获取上传成功的文件名
            files = getFilesByService(json, conditionVo.getComponentType());
        }

        for (String file : files) {
            if (PubUtil.isNotEmpty(file)) {
                //查询文件是否已经存在
                List<CommLogFileRcdEntity> commLogFileRcdlist = PubUtil.convertListMapToObject(
                        this.sqlMapDao.selectList("loadFileMonitor.getLogFileRcd", file), CommLogFileRcdEntity.class);
                if (PubUtil.isEmpty(commLogFileRcdlist)) {
                    loadFileNService.saveCommLogFileRcdEntity(conditionVo, file);
                } else {
                    for (CommLogFileRcdEntity commLogFileRcdEntity : commLogFileRcdlist) {
                        //非导入成功的文件，更新成“等待下载”的状态
                        if (!"3".equals(commLogFileRcdEntity.getFileSt())) {
                            commLogFileRcdEntity.setFileSt("0");
                            loadFileNService.updateCommLogFileRcdEntity(commLogFileRcdEntity);
                        }
                    }
                }
            }
        }
    }

    // todo 下载对应的文件，并且入库

    /**
     * loadFiles(下载对应的文件，并且入库)
     *
     * @param conditionVo
     * @return
     * @throws Exception
     * @Exception 异常对象
     */
    @Transactional
    public void loadFiles(LoadFileParamVo conditionVo) throws Exception {
        //更改文件下载状态
        List<CommLogFileRcdEntity> commLogFileRcdlist =
                PubUtil.convertListMapToObject(
                        this.sqlMapDao.selectList("loadFileMonitor.getLogFileRcdByFileList", conditionVo),
                        CommLogFileRcdEntity.class);

        for (CommLogFileRcdEntity commLogFileRcdEntity : commLogFileRcdlist) {
            //等待下载的文件，更新成下载中的状态
            commLogFileRcdEntity.setFileSt("1");
            loadFileNService.updateCommLogFileRcdEntity(commLogFileRcdEntity);
        }

        //下发命令给设备，对文件进行下载入库
        HashMap<String, String> jsonMap = new HashMap<String, String>();

        String[] fileNames = conditionVo.getFileNames();

        jsonMap.put("carId", conditionVo.getCarIds()[0]);
        jsonMap.put("canId", conditionVo.getComponentType());
        jsonMap.put("fileSize", String.valueOf(fileNames.length));
        jsonMap.put("ftpUrl", conditionVo.getFtpUrl());
        for (int i = 0; i < fileNames.length; i++) {
            jsonMap.put("file" + i, fileNames[i]);
        }

        String json = JsonUtil.getJsonStringFromMap(jsonMap);

        //下发下载的命令到设备端
        Object[] resultData = webServiceBSService.sendToCommModel(json, "29");
        String resultJson = (resultData != null ? (String) resultData[0] : "");
        Map resultMap = JsonUtil.getMapFromJsonString(resultJson);
        JSONObject headJSONObject = (JSONObject) resultMap.get("head");

        //对返回的结果进行解析，如果返回错误的话进行错误的提示，否则不进行处理
        if (headJSONObject != null) {
            String state_code = headJSONObject.get("state_code").toString();
            String state_desc = headJSONObject.get("state_desc").toString();
            if ("1".equals(state_code)) {
                throw new BusinessException(MsgType.ERROR.getFlag(), "下发命令发生错误:" + state_desc);
            }
        }
    }

    /**
     * getFilesByService(调用通信模块服务获取文件名)
     *
     * @param json 发送给通信模块的数据  eg:{"0":["2014-07-16 14:43:46","2014-07-16 14:43:46"]}
     * @return
     */
    private ArrayList<String> getFilesByService(String json, String dataType) throws Exception {
        logger.debug("下发通讯的命令：" + json);

        WebServiceClient webServiceClient = new WebServiceClient();
        ArrayList<String> fileList = new ArrayList<String>();
        Object[] filesData;
        String fileJson = "";
        try {
            // 调用服务获取文件名JSON
            filesData = webServiceClient.getCommWsClient(getParamMap(json, "04"), getMethod());
            logger.debug("通讯返回的结果：" + JsonUtil.toJSONString(filesData));

            fileJson = (filesData != null ? (String) filesData[0] : "");
            Map fileMap = JsonUtil.getMapFromJsonString(fileJson);
            JSONObject headJSONObject = (JSONObject) fileMap.get("head");
            if (headJSONObject != null) {
                String state_code = headJSONObject.get("state_code").toString();
                if ("0".equals(state_code)) {
                    JSONObject bodyJSONObject = (JSONObject) fileMap.get("body");
                    if (bodyJSONObject != null && !bodyJSONObject.isEmpty()) {
                        JSONArray bodyJSONArray = bodyJSONObject.getJSONArray("14");
                        if (bodyJSONArray != null) {
                            for (Object file : bodyJSONArray.toArray()) {
                                JSONObject fileJSONObject = (JSONObject) file;
                                Iterator keyIter = fileJSONObject.keys();
                                while (keyIter.hasNext()) {
                                    String key = (String) keyIter.next();
                                    fileList.add(fileJSONObject.get(key).toString());
                                }
                            }
                        }
                    }
                } else {
                    throw new BusinessException(MsgType.ERROR.getFlag(), headJSONObject.get("state_desc").toString());
                }
            }

            //得到的结果转换成文件数组
        } catch (Exception e) {
            logger.error(json + "调用通讯服务出现错误:" + e.getMessage() + "返回数据:" + fileJson, e);
            throw new BusinessException(MsgType.ERROR.getFlag(), "调用通讯服务出现错误:" + e.getMessage());
        }
        return fileList;
    }

    private String getMethod() {
        return "sendBSData";
    }

    private HashMap<String, Object> getParamMap(String json, String dataType) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("dataString", json);
        map.put("dataType", dataType);
        return map;
    }

    // todo 获取时间断点区间

    /**
     * 获取时间断点区间
     *
     * @param conditionVo
     * @return
     * @throws Exception
     */
    private HashMap<String, Object> getTimeBreak(LoadFileParamVo conditionVo) throws Exception {
        HashMap<String, Object> timeBreakMap = new HashMap<String, Object>();  //时间断点时间记录
        HashMap<String, String[]> timeArrayMap = new HashMap<String, String[]>(); //发送设备的时间区间

        //得到时间段内拥有的文件，并且返回文件所占用的时间区间
        //获取devId
        String devId = getDevId(conditionVo);
        conditionVo.setDevId(devId);
        List<CommLogFileRcdEntity> commLogFileRcdByFileDateList = getCommLogFileRcdList(conditionVo);

        //遍历时间区间，过滤查询时段，得到未下载的时间区间
        if (PubUtil.isEmpty(commLogFileRcdByFileDateList)) {
            timeArrayMap.put("0", new String[]{conditionVo.getBeginTime(), conditionVo.getEndTime()});
        } else {
            int size = commLogFileRcdByFileDateList.size();
            int tag = 0;

            //第一个时间区间
            CommLogFileRcdEntity firstFile = commLogFileRcdByFileDateList.get(0);

            if (new UFDateTime(firstFile.getFileBeginTime()).after(new UFDateTime(conditionVo.getBeginTime()))) {
                timeArrayMap.put(String.valueOf(tag), new String[]{conditionVo.getBeginTime(), firstFile.getFileBeginTime()});
                tag++;
            }

            //最后一个时间区间
            CommLogFileRcdEntity lastFile = commLogFileRcdByFileDateList.get(size - 1);

            if (new UFDateTime(conditionVo.getEndTime()).after(new UFDateTime(lastFile.getFileEndTime()))) {
                timeArrayMap.put(String.valueOf(tag), new String[]{lastFile.getFileEndTime(), conditionVo.getEndTime()});
                tag++;
            }

            //中间的时间区间
            CommLogFileRcdEntity currFile = null;
            CommLogFileRcdEntity nextFile = null;


            for (int i = 0; i < size - 1; i++) {
                currFile = commLogFileRcdByFileDateList.get(i);
                nextFile = commLogFileRcdByFileDateList.get(i + 1);

                if (new UFDateTime(currFile.getFileEndTime()).before(new UFDateTime(nextFile.getFileBeginTime()))) {
                    timeArrayMap.put(String.valueOf(tag), new String[]{currFile.getFileEndTime(), nextFile.getFileBeginTime()});
                    tag++;
                }
            }
        }

        if (timeArrayMap.size() > 0) {
            timeBreakMap.put("data", timeArrayMap);
            timeBreakMap.put("type1", "05");
            timeBreakMap.put("type2", conditionVo.getComponentType());
            timeBreakMap.put("devId", devId);
        }
        return timeBreakMap;
    }


    /**
     * 获取设备ID
     *
     * @param conditionVo
     * @return
     * @throws Exception
     */
    public String getDevId(LoadFileParamVo conditionVo) throws Exception {
        HashMap<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("RLTV_CAR_ID", conditionVo.getCarIds()[0]);
        Object devId = this.sqlMapDao.selectOne("loadFileMonitor.getDevId", paramMap);
        if (devId != null) {
            return devId.toString();
        } else {
            throw new BusinessException(MsgType.ERROR.getFlag(), "车辆与设备关系未维护!");
        }
    }

    /**
     * 得到时间段内拥有的文件，并且返回文件所占用的时间区间
     *
     * @param conditionVo
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<CommLogFileRcdEntity> getCommLogFileRcdList(LoadFileParamVo conditionVo) {
        List<CommLogFileRcdEntity> list = PubUtil.convertListMapToObject(
                this.sqlMapDao.selectList("loadFileMonitor.getLogFileRcdList", conditionVo), CommLogFileRcdEntity.class);
        return list;
    }

    /**
     * 得到时间段内拥有的文件，并且返回文件详细信息
     *
     * @param entity
     * @return
     */
    public List<CommLogFileRcdEntity> getCommLogFileRcdByTimeList(LoadFileParamVo entity) {
        List<CommLogFileRcdEntity> list = PubUtil.convertListMapToObject(
                this.sqlMapDao.selectList("loadFileMonitor.getLogFileRcdByTimeList", entity), CommLogFileRcdEntity.class);
        return list;
    }

    public List<CommLogFileRcdEntity> getCommLogFileRcdByFileList(LoadFileParamVo entity) {
        List<CommLogFileRcdEntity> list = PubUtil.convertListMapToObject(
                this.sqlMapDao.selectList("loadFileMonitor.getLogFileRcdByFileList", entity), CommLogFileRcdEntity.class);
        return list;
    }

}
